package com.xinggq.pay.service.pay.channel.yse.pay.desk.dto;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.xinggq.pay.api.dto.YseCommonPayReqDTO;
import com.xinggq.pay.service.entity.YsePayConfigEntity;
import com.xinggq.pay.service.pay.channel.PayChannelResp;
import com.xinggq.pay.service.pay.channel.yse.enums.YseMethodEnum;
import com.xinggq.pay.service.pay.channel.yse.utils.YseUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * 银盛收银台参数封装
 *
 * @author xgq
 * @since 2025/9/11 13:45
 *
 * */
@Data
@Slf4j
public class YsePayDeskRespDTO implements PayChannelResp<YsePayDeskRespDTO> {

  private InnerParamDto requestData;
  private String requestGateWay;
  private String parameters;

  @Override
  @JsonIgnore
  public YsePayDeskRespDTO getCommonResp() {
    return this;
  }

  /**
   * 定义静态内部类，用于封装银盛收银台参数
   */
  @Data
  public static class InnerParamDto {

    /**
     * 接口名称 固定值：ysepay.online.directpay.createbyuser
     */
    private String method;
    /**
     * 在银盛支付开设的服务商商户号，请联系客户经理提供
     */
    @JsonProperty("partner_id")
    private String partnerId;
    /**
     * 发送请求的时间，格式"yyyy-MM-dd HH:mm:ss" 示例值：2014-07-24 03:07:50
     */
    private String timestamp;
    /**
     * 商户网站使用的编码格式，如UTF-8、GBK、GB2312等，默认值 GBK
     */
    private String charset;
    /**
     * 报文签名算法，默认RSA
     */
    @JsonProperty("sign_type")
    private String signType;
    /**
     * RSA签名字符串，再用Base64编码
     */
    private String sign;
    /**
     * 交易成功异步通知到商户的后台地址，多个url用分隔符“,”分开，格式如：url1,url2,url3，支持TLS1.0、TLS1.1、TLS1.2
     */
    @JsonProperty("notify_url")
    private String notifyUrl;
    /**
     * 接口版本3.0 /3.4,当前版本3.4
     */
    private String version;
    /**
     * 商户系统生成的订单号，须保证在商户端不重复，生成规则前8位必须为交易日期，如20220525，范围跨度支持包含当天在内的前后一天，且只能由大小写英文字母、数字、下划线及横杠组成，示例值：202205256843192280647118
     */
    @JsonProperty("out_trade_no")
    private String outTradeNo;
    /**
     * 商户日期(该参数做交易与查询时需要一致) 该日期需在当日的前后一天时间范围之内 示例值：20180525
     */
    private String shopdate;
    /**
     * 订单备注
     */
    private String subject;
    /**
     * 该笔订单的资金总额，单位为RMB-Yuan。取值范围为[0.01，100000000.00]，精确到小数点后两位。Number(10,2)指10位长度，2位精度
     */
    @JsonProperty("total_amount")
    private String totalAmount;
    /**
     * 收款商户号（由银盛支付生成并下发）
     */
    @JsonProperty("seller_id")
    private String sellerId;
    /**
     * 设置未付款交易的超时时间，一旦超时，该笔交易就会自动被关闭，取值范围：1m～15d。m-分钟，h-小时，d-天。该参数数值不接受小数点，如1.5h，可转换为90m。注意：设置了未付款交易超时时间的情况下，若我司在限定时间内没有收到成功支付通知，则会关闭交易，关闭后该笔交易若付款方支付成功的情况下，会自动原路退款至付款方。示例值 96h 代表96小时后订单自动关闭
     */
    @JsonProperty("timeout_express")
    private String timeoutExpress;
    /**
     * 直连银行信息,和paymode配合使用，支持卡类型, bank_type非空时，此处必填debit:借记卡;credit:信用卡
     */
    @JsonProperty("support_card_type")
    private String supportCardType;
    /**
     * 业务代码 ，请联系银盛客户经理获取。注意：业务代码非固定值，不同到账方式需要传不同的业务代码
     */
    @JsonProperty("business_code")
    private String businessCode;
    /**
     * 银盛支付处理完请求后，当前页面自动跳转到商户网站里指定页面的http路径。
     */
    @JsonProperty("return_url")
    private String returnUrl;
  }

  public static YsePayDeskRespDTO buildYsePayDeskDTO(YseCommonPayReqDTO payParamDto,
      YsePayConfigEntity ysePayConfig) {
    InnerParamDto payDeskDTO = new InnerParamDto();
    payDeskDTO.setMethod(ysePayConfig.getMethod());
    payDeskDTO.setPartnerId(ysePayConfig.getPartnerId());
    payDeskDTO.setTimestamp(DateUtil.now());
    payDeskDTO.setCharset("utf-8");
    payDeskDTO.setSignType("RSA");
    payDeskDTO.setNotifyUrl(ysePayConfig.getNotifyUrl());
    payDeskDTO.setVersion(YseMethodEnum.DESK_PAY.getVersion());
    payDeskDTO.setOutTradeNo(payParamDto.getChannelOutTradeNo());
    payDeskDTO.setShopdate(DateUtil.now());
    payDeskDTO.setSubject("网银支付");
    payDeskDTO.setTotalAmount(String.valueOf(payParamDto.getTotalAmount()));
    payDeskDTO.setSellerId(ysePayConfig.getSellerId());
    payDeskDTO.setTimeoutExpress("500m");
    payDeskDTO.setSupportCardType("debit");
    payDeskDTO.setBusinessCode(ysePayConfig.getBusinessCode());
    payDeskDTO.setReturnUrl(payParamDto.getBankParams().getReturnUrl());
    payDeskDTO.setSign(YseUtil.generateSignWithOutEncode(JSONObject.toJSONString(payDeskDTO)));
    YsePayDeskRespDTO ysePayDeskDTO = new YsePayDeskRespDTO();
    ysePayDeskDTO.setRequestData(payDeskDTO);
    ysePayDeskDTO.setRequestGateWay(YseMethodEnum.DESK_PAY.getGatewayUrl());
    ysePayDeskDTO.setParameters(
        YseMethodEnum.DESK_PAY.getGatewayUrl() + "?" + YseUtil.mapToSortedString(
            BeanUtil.beanToMap(payDeskDTO, true, true)));
    return ysePayDeskDTO;
  }
}